﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using DiscoveryLogic.UI.Layouts.Models;
using DiscoveryLogic.UI.Layouts.ContentScreens;
using DiscoveryLogic.DataServices.DataSources;
using System.Threading;

namespace DiscoveryLogic.UI.Layouts.Controls
{
    public partial class PieChart : UserControl
    {
        #region Private Variables

            // The different actions for the pie chart popup
            private enum AllocationAction { NewContributionAmount, TransferFunds, ModifyContributionAmount }

            // List of pie slices in this pie chart
            private List<PieSlice> pieSliceList;

            // Manages common mouse events
            private MouseManager mouseEventManager;

            // Delegate that is invoked from pie slice
            public fundDetached callAttachFund;

            private double radius;
            private double centerX;
            private double centerY;
            private double currentAngle;
            private double totalDegrees;

            private double contributionAmount = 1000;
            private double totalPieAmount;
            private double totalContributionPercent;

            private bool isSliceOff;
            private bool isOverlapSlice;
            private int overlapSliceId;
            private Ellipse firstPie;
            private Ellipse pieShadow;

            private readonly string[] allocationActionText;

            private PieSlice currentPieSlice;
            private EnrollmentFund currentFund;

            private bool isStaticPieChart;
            private bool fundTransferAllowed;
            private bool chartActionsAllowed = true;
            private bool isAllocationChart;
            private bool canModifyContribution = true;

        #endregion

        #region Constructors

            public PieChart(Point center, double pieRadius, bool isStaticChart, bool allowFundTransfer) :
                this(center, pieRadius)
            {
                isStaticPieChart = isStaticChart;
                fundTransferAllowed = allowFundTransfer;
            }

            /// <summary>
            /// Create a new PieChart control
            /// </summary>
            /// <param name="center">The center of the pie chart</param>
            /// <param name="pieRadius">The radius of the circle</param>
            public PieChart(Point center, double pieRadius)
            {
                // Required to initialize variables
                InitializeComponent();

                allocationActionText = new string[3] { 
                    (string)Resources["Res_SetContribution"],
                    (string)Resources["Res_TransferFunds"],
                    (string)Resources["Res_ChangeContribution"]};


                mouseEventManager = new MouseManager();

                pieSliceList = new List<PieSlice>();

                centerX = center.X;
                centerY = center.Y;
                radius = pieRadius;
                currentAngle = 0;
                totalDegrees = 360;

                // Create slider and put into allocation slider popup canvas
                AllocationSlider.Minimum = 0;
                AllocationSlider.Maximum = 100;

                //JAIMERTODO: allocationSlider.ShowSliderLabel(true);                                        
                AllocationPopup.SetValue(Canvas.LeftProperty, centerX - (double)AllocationPopup.Width / 2);
                AllocationPopup.SetValue(Canvas.TopProperty, centerY - (double)AllocationPopup.Height / 2);
                AllocationSliderCanvas.Opacity = 0;

                // Create the initial dotted pie and shadow
                CreateInitialPie();

                // Position the chart gloss
                //PieChartGloss.SetValue(Canvas.TopProperty, centerY - PieChartGloss.Height / 2);
                //PieChartGloss.SetValue(Canvas.LeftProperty, centerX - PieChartGloss.Width / 2);
            }

        #endregion

        #region Public Properties

            public double Radius
            {
                get { return radius; }
                set { radius = value; }
            }

            public bool IsAllocationChart
            {
                get { return isAllocationChart; }
                set { isAllocationChart = value; }
            }

            public double TotalPieAmount
            {
                get { return totalPieAmount; }
                set { }
            }

            public bool ChartActionsAllowed
            {
                get { return chartActionsAllowed; }
                set { chartActionsAllowed = value; }
            }

        #endregion

        #region Public Methods

            public bool FundExists(FundTypes fundType)
            {
                for (int i = 0; i < pieSliceList.Count; i++)
                {
                    if (fundType == pieSliceList[i].Fund.FundType)
                    {
                        return true;
                    }
                }

                return false;
            }

            public List<PieSlice> GetPieSliceList()
            {
                return pieSliceList;
            }

            public PieSlice GetPieSlice(string fundName)
            {
                for (int i = 0; i < pieSliceList.Count; i++)
                {
                    if (fundName == pieSliceList[i].Fund.FundName)
                    {
                        return pieSliceList[i];
                    }
                }

                return null;
            }

            /// <summary>
            /// The total contribution percent
            /// </summary>
            public double TotalContributionPercent
            {
                get
                {
                    // Recalculate total contribution percent
                    totalContributionPercent = 0;

                    for (int i = 0; i < pieSliceList.Count; i++)
                    {
                        totalContributionPercent += pieSliceList[i].SliceContribution;
                    }

                    return totalContributionPercent;
                }
                set { totalContributionPercent = value; }
            }

            /// <summary>
            /// Add slice to the pie chart
            /// </summary>
            /// <param name="amount">Amount in dollars this slice represents</param>
            /// <param name="percent">Contribution percentage for this slice(fund)</param>
            /// <param name="fund">The fund this slice represents</param>
            /// <param name="isDummyFund">This fund has no value but is meant to be a placeholder so it 
            /// has 10% thickness of the pie. It is also grey in color.</param>
            public void AddSlice(double amount, double percent, EnrollmentFund fund)
            {
                // Update totals
                totalPieAmount += amount;
                totalContributionPercent += percent;

                if (contributionChanged != null)
                {
                    contributionChanged(this, new EventArgs());
                }

                if (pieSliceList.Count == 0)
                {
                    // Hide initial ellipse
                    firstPie.Opacity = 0;
                    pieShadow.Opacity = 0.5;
                }
                else
                {
                    // Update each slice's total amount
                    foreach (PieSlice p in pieSliceList)
                    {
                        p.TotalPieAmount = totalPieAmount;
                    }
                }

                // Create new PieSlice
                PieSlice slice = new PieSlice(amount, totalPieAmount, percent, fund);

                // Set properties
                slice.sliceDrag += new EventHandler(this.OnSliceDrag);
                slice.pieSliceMouseDown += new EventHandler(this.OnPieSliceMouseDown);
                slice.pieSliceMouseUp += new MouseEventHandler(this.OnPieSliceMouseUp);
                slice.Id = pieSliceList.Count;
                slice.SliceContribution = percent;

                if (isAllocationChart)
                {
                    slice.Fund.HideFundValueLabel(true);
                }

                // Add slice to list
                pieSliceList.Add(slice);

                // Add slice to canvas
                PieChartCanvas.Children.Add(slice);

                // If this is a static chart then remove handlers from slice to
                // make it non-interactive
                if (isStaticPieChart)
                {
                    slice.RemoveAllHandlers();
                }
            }



            /// <summary>
            /// Remove the pie slice from the pie chart
            /// </summary>
            /// <param name="slice"></param>
            public void RemoveSlice(PieSlice slice)
            {
                // Remeve slice from list
                if (pieSliceList.Contains(slice))
                {
                    pieSliceList.Remove(slice);
                }

                // Remove slice from canvas
                if (PieChartCanvas.Children.Contains(slice))
                {
                    PieChartCanvas.Children.Remove(slice);
                }

                // Update totals
                totalPieAmount -= slice.SliceAmount;
                totalContributionPercent -= slice.SliceContribution;

                // Raise contributionChanged event which is handled
                // in Enrollment.xaml.cs
                if (contributionChanged != null)
                {
                    contributionChanged(this, new EventArgs());
                }

                // Tell each pie slice about the updated total
                foreach (PieSlice p in pieSliceList)
                {
                    p.TotalPieAmount = totalPieAmount;
                }

                // If there are no more pie slices after this one is removed,
                // then set visible the first pie slice
                if (pieSliceList.Count == 0)
                {
                    pieShadow.Opacity = 0;
                    firstPie.Opacity = 1;
                    // Reset to initial attributes
                    firstPie.Fill = new SolidColorBrush(Colors.Transparent);
                    firstPie.Stroke = new SolidColorBrush(Colors.LightGray);
                    firstPie.StrokeThickness = 3;
                }
            }

            /// <summary>
            /// Removes the pie slices with the given fund types.
            /// Note: this method does not update pie total value or contribution.
            /// This method is used for rebalancing when the total pie value/
            /// contribution doesn`t change
            /// </summary>
            /// <param name="fundType"></param>
            public void RebalanceRemoveSlice(PieSlice slice)
            {
                // Remove slice from list
                pieSliceList.Remove(slice);

                // Remove slice from canvas
                PieChartCanvas.Children.Remove(slice);

            }

            /// <summary>
            /// Redraw the slices
            /// </summary>
            public void DrawSlices()
            {
                Point last = new Point(centerX - radius, centerY);
                double total = totalPieAmount;
                double lastPercent = 0.0;

                for (int j = 0; j < EnrollmentFund.numFundTypes; j++)
                {
                    for (int i = 0; i < pieSliceList.Count; i++)
                    {
                        PieSlice s = pieSliceList[i];

                        if ((int)s.Fund.FundType == j)
                        {
                            double piePercent;
                            if (total > 0)
                            {
                                piePercent = 100 * s.SliceAmount / total;
                            }
                            else
                            {
                                piePercent = 100;
                            }
                            
                            last = CreateSlicePath(s, piePercent, lastPercent, last);
                            lastPercent += piePercent;
                        }
                    }
                }
            }

            /// <summary>
            /// Tests if the mouse is over a slice
            /// </summary>
            /// <param name="e"></param>
            /// <returns></returns>
            public bool HitTestHighlight(MouseEventArgs e)
            {
                isOverlapSlice = false;

                foreach (PieSlice p in pieSliceList)
                {
                    p.ResetColor();
                    p.LowerSlice();
                }

                double distanceAwayX, distanceAwayY;

                // If there are no pie slices
                if (pieSliceList.Count == 0)
                {
                    distanceAwayX = e.GetPosition(firstPie).X;
                    distanceAwayY = e.GetPosition(firstPie).Y;


                    if (distanceAwayX > 0 && distanceAwayX < radius * 2 &&
                        distanceAwayY > 0 && distanceAwayY < radius * 2)
                    {
                        firstPie.Stroke = new SolidColorBrush(Utils.HexToColor("#FF1B60AC"));
                        firstPie.StrokeThickness = 4;
                        isOverlapSlice = true;
                        overlapSliceId = -1;
                        return true;
                    }
                    else
                    {
                        firstPie.Stroke = new SolidColorBrush(Colors.LightGray);
                        firstPie.StrokeThickness = 3;
                    }
                }

                // If there are pie slices
                for (int i = 0; i < pieSliceList.Count; i++)
                {
                    distanceAwayX = e.GetPosition(null).X;
                    distanceAwayY = e.GetPosition(null).Y;

                    Path p = pieSliceList[i].slicePath;
                    IEnumerable<UIElement> test = System.Windows.Media.VisualTreeHelper.FindElementsInHostCoordinates(new Point(distanceAwayX, distanceAwayY), p) as List<UIElement>;
                    //IEnumerable<UIElement> test = p.HitTest(new Point(distanceAwayX, distanceAwayY));

                    foreach (UIElement u in test)
                    {
                        if (u.GetType() == typeof(Path))
                        {
                            // Find out which path this is and then animate it to come out
                            for (int j = 0; j < pieSliceList.Count; j++)
                            {
                                if (((Path)u).Equals(pieSliceList[j].slicePath))
                                {
                                    pieSliceList[j].SetHighlightColor();
                                    pieSliceList[j].LiftSlice();
                                    break;
                                }
                            }

                            //pieSliceList[i].SetRed();
                            isOverlapSlice = true;
                            overlapSliceId = i;
                            return true;
                        }
                    }





                }

                return false;
            }

            /// <summary>
            /// Add fund to this pie chart because a fund
            /// has been dragged onto the pie chart.
            /// </summary>
            /// <param name="fund"></param>
            public void AddFund(EnrollmentFund fund)
            {
                if (isOverlapSlice == true)
                {
                    isOverlapSlice = false;

                    currentFund = fund;

                    currentPieSlice = null;

                    AllocationSliderCanvas.Opacity = 1;
                    AllocationSliderCanvas.SetValue(Canvas.ZIndexProperty, 3);
                    // Set text to "Contribution Amount"
                    AllocationPopupLabel.Text = allocationActionText[(int)AllocationAction.NewContributionAmount];
                }
            }

            /// <summary>
            /// Add a fund to this pie chart directly without
            /// popping up the contribution percentage popup window
            /// </summary>
            /// <param name="fund"></param>
            /// <param name="contributionPercent"></param>
            public void AddFund(EnrollmentFund fund, double contributionPercent)
            {
                isOverlapSlice = false;
                AddSlice(TotalPieAmount * 0.1, contributionPercent, fund);
                DrawSlices();
            }

            /// <summary>
            /// Hides or shows the fund icon of the slices
            /// </summary>
            /// <param name="hide"></param>
            public void HideFundIcons(bool hide)
            {
                for (int i = 0; i < pieSliceList.Count; i++)
                {
                    pieSliceList[i].HideFundIcon(hide);
                }
            }

            /// <summary>
            /// Hides or shows the fund names beside the fund icon
            /// </summary>
            /// <param name="hide"></param>
            public void HideFundNameLabels(bool hide)
            {
                for (int i = 0; i < pieSliceList.Count; i++)
                {
                    pieSliceList[i].Fund.HideFundNameLabel(hide);
                }
            }

            /// <summary>
            /// Hides or shows the fund value labels beside the fund icon
            /// </summary>
            /// <param name="hide"></param>
            public void HideFundValueLabels(bool hide)
            {
                for (int i = 0; i < pieSliceList.Count; i++)
                {
                    pieSliceList[i].Fund.HideFundValueLabel(hide);
                }
            }

            public FundTypes[] GetSliceFundTypes()
            {
                List<FundTypes> fundTypes = new List<FundTypes>();

                for (int i = 0; i < pieSliceList.Count; i++)
                {
                    FundTypes currentFundType = pieSliceList[i].Fund.FundType;

                    if (!fundTypes.Contains(currentFundType))
                    {
                        fundTypes.Add(currentFundType);
                    }
                }

                return fundTypes.ToArray();
            }

            public void LiftSlices(FundTypes fundType)
            {
                for (int i = 0; i < pieSliceList.Count; i++)
                {
                    if (pieSliceList[i].Fund.FundType == fundType)
                    {
                        pieSliceList[i].LiftSlice();
                    }
                }
            }

            public void LowerSlices(FundTypes fundType)
            {
                for (int i = 0; i < pieSliceList.Count; i++)
                {
                    if (pieSliceList[i].Fund.FundType == fundType)
                    {
                        pieSliceList[i].LowerSlice();
                    }
                }
            }

            /// <summary>
            ///  Return the funds of a specified fund type
            /// </summary>
            public Dictionary<FundTypes, List<PieSlice>> GetFunds()
            {
                Dictionary<FundTypes, List<PieSlice>> fundTable = new Dictionary<FundTypes, List<PieSlice>>();

                List<PieSlice>[] matchedSlicesList = new List<PieSlice>[EnrollmentFund.numFundTypes];

                for (int i = 0; i < pieSliceList.Count; i++)
                {
                    EnrollmentFund currentFund = pieSliceList[i].Fund;
                    FundTypes currentFundType = currentFund.FundType;

                    if (!fundTable.ContainsKey(currentFundType))
                    {
                        matchedSlicesList[(int)currentFundType] = new List<PieSlice>();
                        fundTable.Add(currentFundType, matchedSlicesList[(int)currentFundType]);
                    }

                    matchedSlicesList[(int)currentFundType].Add(pieSliceList[i]);
                }

                return fundTable;
            }

            public void ColorSlicesOpaque()
            {
                for (int i = 0; i < pieSliceList.Count; i++)
                {
                    pieSliceList[i].SetOpaqueColor();
                }
            }

        #endregion

        #region Helper Methods

            /// <summary>
            /// Create the path geometry for the path object
            /// in a pie slice.
            /// </summary>
            /// <param name="s">PieSlice object to set</param>
            /// <param name="piePercent">Percentage of the pie this slice represents</param>
            /// <param name="lastPercent">Previous percentage</param>
            /// <param name="last">The point where the previous slice left off</param>
            /// <returns></returns>
            private Point CreateSlicePath(PieSlice s, double piePercent, double lastPercent, Point last)
            {
                bool isLargeAngle = piePercent >= 50;
                double previousAngleinRadians = lastPercent * .02 * Math.PI;
                lastPercent += piePercent;
                double currentAngleinRadians = lastPercent * .02 * Math.PI;

                double x = centerX - (radius * Math.Cos(currentAngleinRadians));
                double y = centerY - (radius * Math.Sin(currentAngleinRadians));

                // Construct slice
                PathFigure pf = new PathFigure();
                pf.StartPoint = new Point(centerX, centerY);

                LineSegment openingls = new LineSegment();
                LineSegment closingls = new LineSegment();

                openingls.Point = new Point(last.X, last.Y);
                closingls.Point = new Point(centerX, centerY);

                ArcSegment arc = new ArcSegment();
                arc.Size = new Size(radius, radius);
                arc.RotationAngle = 0;
                arc.IsLargeArc = isLargeAngle;
                arc.SweepDirection = SweepDirection.Clockwise;
                if (Math.Round(piePercent) >= 100)
                {
                    y += 0.01;
                }
                arc.Point = new Point(x, y);

                pf.Segments = new PathSegmentCollection();
                pf.Segments.Add(openingls);
                pf.Segments.Add(arc);
                pf.Segments.Add(closingls);

                PathGeometry pg = new PathGeometry();
                pg.Figures = new PathFigureCollection();
                pg.Figures.Add(pf);

                // Create points for icon and animation
                double angleTooltip = previousAngleinRadians + (piePercent * .01 * Math.PI);
                double tooltipX = centerX - (radius * 0.9) * Math.Cos(angleTooltip);
                double tooltipY = centerY - (radius * 0.9) * Math.Sin(angleTooltip);
                double animateX = centerX - (radius * 0.1) * Math.Cos(angleTooltip);
                double animateY = centerY - (radius * 0.1) * Math.Sin(angleTooltip);

                Point toolTipPoint = new Point(tooltipX, tooltipY);
                Point animationPoint = new Point(animateX - centerX, animateY - centerY);

                // Pass into pie slice
                if (piePercent >= 100)
                {
                    s.SetSlice(pg, toolTipPoint, animationPoint, 0, new Point(centerX, centerY));
                }
                else
                {
                    s.SetSlice(pg, toolTipPoint, animationPoint, 2, new Point(centerX, centerY));
                }

                last.X = x;
                last.Y = y;

                return last;
            }

            /// <summary>
            /// Create the inital dotted line pie and shadow
            /// </summary>
            private void CreateInitialPie()
            {
                // Create initial pie
                firstPie = new Ellipse();

                // Set properties
                firstPie.Width = radius * 2;
                firstPie.Height = radius * 2;
                firstPie.Fill = new SolidColorBrush(Colors.Transparent);
                firstPie.Stroke = new SolidColorBrush(Colors.LightGray);
                firstPie.StrokeThickness = 3;

                // Set stroke for initial pie
                DoubleCollection dashes = new DoubleCollection();
                dashes.Add(3);
                dashes.Add(3);
                firstPie.StrokeDashArray = dashes;
                firstPie.StrokeDashCap = PenLineCap.Square;

                // Set position
                firstPie.SetValue(Canvas.LeftProperty, centerX - radius);
                firstPie.SetValue(Canvas.TopProperty, centerY - radius);


                // Create shadow pie
                pieShadow = new Ellipse();

                // Set shadow properties
                pieShadow.Width = radius * 2;
                pieShadow.Height = radius * 2;
                pieShadow.Fill = CreateShadowBrush();
                pieShadow.SetValue(Canvas.LeftProperty, centerX - radius);
                pieShadow.SetValue(Canvas.TopProperty, centerY - radius + 30);
                pieShadow.Opacity = 0;

                // Add default pie and shadow to canvas
                PieChartCanvas.Children.Add(pieShadow);

                PieChartCanvas.Children.Add(firstPie);
            }

            /// <summary>
            /// Create a brush to mimic a shadow
            /// </summary>
            /// <returns></returns>
            private RadialGradientBrush CreateShadowBrush()
            {
                // Add brush to fill property of shadow
                RadialGradientBrush rgb = new RadialGradientBrush();
                GradientStop gs1 = new GradientStop();
                GradientStop gs2 = new GradientStop();
                GradientStop gs3 = new GradientStop();

                gs1.Color = Utils.HexToColor("#AF000000");
                gs1.Offset = 0.72;
                gs2.Color = Utils.HexToColor("#00000000");
                gs2.Offset = 2;
                gs2.Color = Colors.Transparent;
                gs3.Offset = 1;

                rgb.GradientStops.Add(gs1);
                rgb.GradientStops.Add(gs2);
                rgb.GradientStops.Add(gs3);

                return rgb;
            }

            /// <summary>
            /// Check position of the pie slice
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="args"></param>
            private void CheckSlicePosition(object sender, MouseEventArgs args)
            {
                isOverlapSlice = false;
                isSliceOff = false;

                // If not chart actions are allowed, return
                if (chartActionsAllowed == false)
                {
                    return;
                }

                double distanceAwayX;
                double distanceAwayY;

                // For each pie slice, reset the color to color of the fund
                // type it represents
                foreach (PieSlice p in pieSliceList)
                {
                    p.ResetColor();
                }

                // Determine if slice falls out of range
                distanceAwayX = args.GetPosition(this).X;
                distanceAwayY = args.GetPosition(this).Y;

                if (
                    distanceAwayX > centerX + radius + 140 || distanceAwayX < centerX - radius - 140 ||
                    distanceAwayY > centerY + radius + 140 || distanceAwayY < centerY - radius - 140)
                {
                    ((PieSlice)sender).SetOffColor();
                    isSliceOff = true;
                }
                // Check if
                else if (
                    distanceAwayX > centerX + radius + 30 || distanceAwayX < centerX - radius - 30 ||
                    distanceAwayY > centerY + radius + 30 || distanceAwayY < centerY - radius - 30)
                {
                    canModifyContribution = false;
                }
                else
                {
                    canModifyContribution = true;
                }

                if (isSliceOff == false)
                {
                    // Determine if slice overlaps another slice
                    for (int i = 0; i < pieSliceList.Count; i++)
                    {
                        distanceAwayX = args.GetPosition(null).X;
                        distanceAwayY = args.GetPosition(null).Y;

                        Path p = pieSliceList[i].slicePath;
                        IEnumerable<UIElement> test = System.Windows.Media.VisualTreeHelper.FindElementsInHostCoordinates(new Point(distanceAwayX, distanceAwayY), p) as List<UIElement>;

                        //IEnumerable<UIElement> test = p.HitTest(new Point(distanceAwayX, distanceAwayY));

                        foreach (UIElement u in test)
                        {
                            if (u.GetType() == typeof(Path) && !u.Equals(((PieSlice)sender).slicePath))
                            {
                                // Find out which path this is and then animate it to come out
                                for (int j = 0; j < pieSliceList.Count; j++)
                                {
                                    if (((Path)u).Equals(pieSliceList[j].slicePath))
                                    {
                                        // Only highlight if fund transfer is allowed
                                        if (fundTransferAllowed)
                                        {
                                            pieSliceList[j].SetHighlightColor();
                                        }
                                        isOverlapSlice = true;
                                        overlapSliceId = j;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }

            }

        #endregion

        #region Event Handlers

            /// <summary>
            /// When a slice is dragged, check its position to see
            /// if it overlaps other slices
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void OnSliceDrag(object sender, EventArgs e)
            {
                MouseEventArgs args = (MouseEventArgs)e;

                CheckSlicePosition(sender, args);
            }

            /// <summary>
            /// On pie slice release, perform an action depending on
            /// its position
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void OnPieSliceMouseUp(object sender, MouseEventArgs e)
            {
                currentPieSlice = ((EnrollmentFund)sender).ParentSlice;

                // Set pie slice properties
                currentPieSlice.SetValue(Canvas.ZIndexProperty, 1);
                //currentPieSlice.SetOpacity(1);

                if (chartActionsAllowed == false)
                {
                    return;
                }

                // Check position of the slice
                CheckSlicePosition(currentPieSlice, e);

                // Depending on what was set during the CheckSlicePosition method,
                // perform an action
                if (isOverlapSlice == true)
                {
                    if (fundTransferAllowed)
                    {
                        // Transfer funds
                        isOverlapSlice = false;
                        AllocationSliderCanvas.Opacity = 1;
                        AllocationSliderCanvas.SetValue(Canvas.ZIndexProperty, 3);
                        // Set text to "Transfer Funds"
                        AllocationPopupLabel.Text = allocationActionText[(int)AllocationAction.TransferFunds];
                    }
                }
                else if (isSliceOff == true)
                {
                    //Remove Slice
                    isSliceOff = false;
                    EnrollmentFund fund = currentPieSlice.DetachFund();
                    RemoveSlice(currentPieSlice);
                    DrawSlices();
                
                    if (callAttachFund != null)
                    {
                        callAttachFund(fund);
                    }
                }
                else if (canModifyContribution == true)
                {
                    // Modifying contribution
                    // Preset slider value to contribution value of fund clicked
                    AllocationSlider.Value = (currentPieSlice.SliceContribution * 100);
                    // Preset slider label
                    double percent = AllocationSlider.Percent;
                    SliderLabel.Text = Math.Round(percent * 100).ToString() + Thread.CurrentThread.CurrentCulture.NumberFormat.PercentSymbol;
                    double sliderThumbPosition = (double)AllocationSlider.GetValue(Canvas.LeftProperty)
                                                + (percent * AllocationSlider.Width);
                    SliderLabel.SetValue(Canvas.LeftProperty, sliderThumbPosition + (-10 * percent));

                    AllocationSliderCanvas.Opacity = 1;
                    AllocationSliderCanvas.SetValue(Canvas.ZIndexProperty, 10);
                    // Set text to "Modify Funds"
                    AllocationPopupLabel.Text = allocationActionText[(int)AllocationAction.ModifyContributionAmount];
                }


            }

            /// <summary>
            /// On mouse down, set opacity and z index of slice
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void OnPieSliceMouseDown(object sender, EventArgs e)
            {
                PieSlice slice = ((EnrollmentFund)sender).ParentSlice;
                slice.SetValue(Canvas.ZIndexProperty, 2);
                //slice.SetOpacity(0.3);
            }

            /// <summary>
            /// On the confirm button of the popup, perform an action
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void OnAllocationConfirmButtonClick(object sender, EventArgs e)
            {
                AllocationSliderCanvas.Opacity = 0;
                AllocationSliderCanvas.SetValue(Canvas.ZIndexProperty, 0);
                double percent = AllocationSlider.Percent;

                if (overlapSliceId != -1 &&
                    overlapSliceId < pieSliceList.Count &&
                    overlapSliceId >= 0)
                {
                    pieSliceList[overlapSliceId].ResetColor();
                    pieSliceList[overlapSliceId].LowerSlice();
                }

                // Setting Contribution Amount
                if (AllocationPopupLabel.Text == allocationActionText[(int)AllocationAction.NewContributionAmount])
                {
                    AddSlice(percent, percent, currentFund);
                    DrawSlices();

                    if (contributionChanged != null)
                    {
                        contributionChanged(this, new EventArgs());
                    }
                }
                // Transferring Funds
                else if (AllocationPopupLabel.Text == allocationActionText[(int)AllocationAction.TransferFunds])
                {
                    pieSliceList[overlapSliceId].SliceAmount += percent * currentPieSlice.SliceAmount;
                    currentPieSlice.SliceAmount -= percent * currentPieSlice.SliceAmount;

                    // If transferred all..
                    if (Math.Round(percent) == 1)
                    {
                        RemoveSlice(currentPieSlice);
                    }

                    DrawSlices();
                }
                // Clicking to modify contribution
                else if (AllocationPopupLabel.Text == allocationActionText[(int)AllocationAction.ModifyContributionAmount])
                {
                    double oldPercent = currentPieSlice.SliceContribution;

                    // Subtract total contribution by slice amount
                    totalContributionPercent -= oldPercent;

                    // Set contribution amount
                    currentPieSlice.SliceContribution = percent;

                    // Update total contribution with new slice contribution amount
                    totalContributionPercent += percent;

                    if (contributionChanged != null)
                    {
                        contributionChanged(this, new EventArgs());
                    }

                    // If this is an allocation pie chart, then contribution
                    // percents are equivalent to amounts, so update totals
                    if (isAllocationChart)
                    {
                        totalPieAmount -= oldPercent;
                        totalPieAmount += percent;
                        currentPieSlice.SliceAmount = percent;
                        DrawSlices();
                    }
                }

                // Reset Slider
                AllocationSlider.Value = (0);
                // Reset Slider label
                percent = AllocationSlider.Percent;
                SliderLabel.Text = Math.Round(percent * 100).ToString() + Thread.CurrentThread.CurrentCulture.NumberFormat.PercentSymbol;
                double sliderThumbPosition = (double)AllocationSlider.GetValue(Canvas.LeftProperty)
                                            + (percent * AllocationSlider.Width);
                SliderLabel.SetValue(Canvas.LeftProperty, sliderThumbPosition + (-10 * percent));
            }

            private void OnAllocationCancelButtonClick(object sender, EventArgs e)
            {
                AllocationSliderCanvas.Opacity = 0;
                AllocationSliderCanvas.SetValue(Canvas.ZIndexProperty, 0);

                // If user selects "cancel" on newly added fund, then return it to fund panel
                if (AllocationPopupLabel.Text == allocationActionText[(int)AllocationAction.NewContributionAmount])
                {
                    if (callAttachFund != null)
                    {
                        callAttachFund(currentFund);
                    }
                }

                // Reset the slice color
                if (overlapSliceId < pieSliceList.Count &&
                    overlapSliceId >= 0)
                {
                    pieSliceList[overlapSliceId].ResetColor();
                }

                // Alert contribution changed
                if (contributionChanged != null)
                {
                    contributionChanged(this, new EventArgs());
                }

                // Reset Slider
                AllocationSlider.Value = (0);
                // Reset Slider label
                double percent = AllocationSlider.Percent;
                SliderLabel.Text = Math.Round(percent * 100).ToString() + Thread.CurrentThread.CurrentCulture.NumberFormat.PercentSymbol;
                double sliderThumbPosition = (double)AllocationSlider.GetValue(Canvas.LeftProperty)
                                            + (percent * AllocationSlider.Width);
                SliderLabel.SetValue(Canvas.LeftProperty, sliderThumbPosition + (-10 * percent));
            }

            private void OnAllocationSliderMoving(object sender, RoutedPropertyChangedEventArgs<double> e)
            {
                double currentContrib = 0;
                double percent = AllocationSlider.Percent;

                // Only alert enrollment when modify contribution dialog is open
                if (contributionChanging != null && AllocationSliderCanvas.Opacity != 0)
                {
                    // If we`re modifying contribution for a slice
                    if (currentPieSlice != null)
                    {
                        currentContrib = currentPieSlice.SliceContribution;
                    }

                    DiscoveryLogic.UI.Layouts.Models.CustomEventArgs args = new DiscoveryLogic.UI.Layouts.Models.CustomEventArgs();
                    args.ContributionOffset = currentContrib - percent;

                    contributionChanging(this, args);
                }
                
                // Move slider label along with slider thumb
                SliderLabel.Text = Math.Round(percent * 100).ToString() + Thread.CurrentThread.CurrentCulture.NumberFormat.PercentSymbol;
                double sliderThumbPosition = (double)AllocationSlider.GetValue(Canvas.LeftProperty)
                                            + (percent * AllocationSlider.Width);
                SliderLabel.SetValue(Canvas.LeftProperty, sliderThumbPosition + (-10 * percent));
            }

        #endregion

        #region Events and Delegates

            public event EventHandler contributionChanged;
            public event EventHandler contributionChanging;
            public delegate void fundDetached(EnrollmentFund fund);

        #endregion
    }
}
